package retrieve;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * Retrieve the data from the server
 * @author yexijiang
 *
 */
public class Retriever extends Thread{
	
	private String name;
	private String ip;
	private int port;
	private String curJson;
	private long sleepMilliSecond;	//	when lost connection, wait a specified time
	
	public Retriever(String name, String ip, int port) {
		this.name = name;
		this.ip = ip;
		this.port = port;
		curJson = "";
		sleepMilliSecond = 1000;
	}
	
	public void run() {
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			Socket serverSocket = null;
			BufferedReader in = null;
	
			try {
				serverSocket = new Socket(ip, port);
				in = new BufferedReader(new InputStreamReader(
						serverSocket.getInputStream()));
				StringBuffer sb = new StringBuffer();
				String line;
				while ((line = in.readLine()) != null) {
					sb.append(line);
				}
//				System.out.println(sb.toString());
				serverSocket.close();
				synchronized(curJson) {
					curJson = sb.toString();
				}
				sleepMilliSecond = 1000;	//	once connect successfully, reset
			} catch (SocketException e) {
				sleepMilliSecond *= 2;
				System.err.println("Connection lost, wait for " + sleepMilliSecond / 1000 + " seconds.");
				try {
					Thread.sleep(sleepMilliSecond);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public synchronized String getCurJsonString() {
		return curJson;
	}
	
	public String getRetrieverName() {
		return name;
	}
	
	public synchronized List<String> getNodeNames() {
		List<String> nodeNames = new ArrayList<String>();
		JsonParser parser = new JsonParser();
		JsonElement jsonElem = parser.parse(curJson);
		if(jsonElem instanceof JsonObject) {
			JsonObject jsonObj = (JsonObject)jsonElem;
			for(Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
				nodeNames.add(entry.getKey());
			}
		}
		
		return nodeNames;
	}
	
	public synchronized String getJsonByNodeName(String nodeName) {
		JsonParser parser = new JsonParser();
		JsonElement jsonElem = parser.parse(curJson);
		if(jsonElem instanceof JsonObject) {
			JsonObject jsonObj = (JsonObject)jsonElem;
			for(Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
				if(entry.getKey().equals(nodeName)) {
					Gson gson = new Gson();
					return gson.toJson(entry.getValue());
				}
			}
		}
		return "";
	}
	
	public static void main(String[] args) {
		String name = "dummy";
		String ip = "127.0.0.1";
		int port = 32165;
		Retriever r = new Retriever(name, ip, port);
	}
	
}
